Conversation
test/test_rack_server.rb
Outdated
| require 'xmlrpc/parser' | ||
| require 'xmlrpc/utils' | ||
|
|
||
| module TestXMLRPC |
There was a problem hiding this comment.
We can remove this because this gem is no longer a default gem. Our test names never conflict with others.
| module TestXMLRPC |
test/test_rack_server.rb
Outdated
| require 'xmlrpc/utils' | ||
|
|
||
| module TestXMLRPC | ||
| class Test_Rack < Test::Unit::TestCase |
There was a problem hiding this comment.
| class Test_Rack < Test::Unit::TestCase | |
| class TestRack < Test::Unit::TestCase |
test/test_rack_server.rb
Outdated
| @@ -0,0 +1,79 @@ | |||
| # coding: utf-8 | |||
There was a problem hiding this comment.
We don't need this because it's the default in recent Ruby.
| # coding: utf-8 |
test/test_rack_server.rb
Outdated
|
|
||
| s.add_introspection | ||
|
|
||
| return s |
test/test_rack_server.rb
Outdated
| module TestXMLRPC | ||
| class Test_Rack < Test::Unit::TestCase | ||
| include Rack::Test::Methods | ||
| include XMLRPC::ParserWriterChooseMixin |
There was a problem hiding this comment.
Can we use XMLRPC::Create.new(XMLRPC::Config.default_writer.new) and XMLRPC::Config.default_parser.new instead?
test/test_rack_server.rb
Outdated
| def assert_call_success(expect, methodname, *args) | ||
| request = create().methodCall(methodname, *args) | ||
| post("/", request, 'CONTENT_TYPE' => 'text/xml') | ||
| ok, param = parser().parseMethodResponse(last_response.body) | ||
| assert(ok) | ||
| assert_equal(expect, param) | ||
| end |
There was a problem hiding this comment.
How about using call helper method like the following and assert_equal?
def call(method_name, *args)
create = XMLRPC::Create.new(XMLRPC::Config.default_writer.new)
request = create.methodCall(method_name, *args)
post("/", request, "CONTENT_TYPE" => "text/xml")
parser = XMLRPC::Config.default_parser.new
parser.parseMethodResponse(last_response.body)
end
def test_rack
assert_equal([true, 9], call("test.add", 4, 5))
assert_equal([false, XMLRPC::FaultException.new(1, "division by zero")],
call("test.div", 1, 0))
# ...
end
test/test_rack_server.rb
Outdated
| def test_rack | ||
| # simple call | ||
| assert_call_success(9, "test.add", 4, 5) | ||
|
|
||
| # fault exception | ||
| assert_call_failure(1, "division by zero", "test.div", 1, 0) | ||
|
|
||
| # introspection | ||
| assert_call_success(["test.add", "test.div", "system.listMethods", "system.methodSignature", "system.methodHelp"], "system.listMethods") | ||
|
|
||
| # default handler (missing handler) | ||
| assert_call_failure(-99, "Method test.nonexisting missing or wrong number of parameters!", "test.nonexisting") | ||
|
|
||
| # default handler (wrong number of arguments) | ||
| assert_call_failure(-99, "Method test.add missing or wrong number of parameters!", "test.add", 1, 2, 3) | ||
|
|
||
| # multibyte characters | ||
| assert_call_success("あいうえおかきくけこ", 'test.add', "あいうえお", "かきくけこ") | ||
| end |
There was a problem hiding this comment.
Could you create one test per test pattern?
For example:
def test_success
assert_call_success(9, "test.add", 4, 5)
end
def test_exception
assert_call_failure(1, "division by zero", "test.div", 1, 0)
enda7463e8 to
c3f00ce
Compare
|
I think I addressed all the issues above. Most of them were to keep the code consistent with the other code/tests. I see this has had a very recent cleanup. |
lib/xmlrpc/server.rb
Outdated
|
|
||
|
|
||
| # Implements a XML-RPC server, which works with Rack | ||
| class RackServer < BasicServer |
There was a problem hiding this comment.
In general, Rack server means Puma, Passenger and so on.
| class RackServer < BasicServer | |
| class RackApplication < BasicServer |
test/test_rack_server.rb
Outdated
| end | ||
|
|
||
| def test_successful_call | ||
| assert_equal([true, 9], call("test.add", 4, 5)) |
There was a problem hiding this comment.
Could you align arguments for easy to read?
| assert_equal([true, 9], call("test.add", 4, 5)) | |
| assert_equal([true, 9], | |
| call("test.add", 4, 5)) |
test/test_rack_server.rb
Outdated
|
|
||
| request = create.methodCall(methodname, *args) | ||
| post("/", request, 'CONTENT_TYPE' => 'text/xml') | ||
| assert(last_response.ok?) |
There was a problem hiding this comment.
Could you use power assert for easy to debug? BTW, when does ok? return false?
| assert(last_response.ok?) | |
| assert do | |
| last_response.ok? | |
| end |
There was a problem hiding this comment.
https://github.com/rack/rack/blob/main/lib/rack/response.rb#L189
ok? checks the HTTP status code for 200. This is mostly relevant for the exceptions, where XMLRPC will still return a HTTP OK (200) status, as opposed to using the HTTP status to signal an error like most REST-based APIs do.
There was a problem hiding this comment.
This results in output like this:
| |
| false
#<Rack::MockResponse:0x00007fbc70b25aa0 @original_headers={"Content-type"=>"text/xml; charset=utf-8"}, @errors="", @status=201, @headers={"content-type"=>"text/xml; charset=utf-8", "content-length"=>"296"}, @writer=#<Method: Rack::MockResponse(Rack::Response::Helpers)#append(chunk) /home/herwin/xmlrpc/vendor/bundle/ruby/3.1.0/gems/rack-3.1.13/lib/rack/response.rb:359>, @block=nil, @body=["<?xml version=\"1.0\" ?><methodResponse><fault><value><struct><member><name>faultCode</name><value><i4>-99</i4></value></member><member><name>faultString</name><value><string>Method test.add missing or wrong number of parameters!</string></value></member></struct></value></fault></methodResponse>\n"], @buffered=true, @length=296, @cookies={}>
/home/herwin/xmlrpc/test/test_rack_server.rb:73:in `call'
/home/herwin/xmlrpc/test/test_rack_server.rb:59:in `test_wrong_number_of_arguments'
56:
57: def test_wrong_number_of_arguments
58: assert_equal([false, XMLRPC::FaultException.new(-99, "Method test.add missing or wrong number of parameters!")],
=> 59: call("test.add", 1, 2, 3))
60: end
I don't think this is the most readable output, I think the better option would be something like:
assert(last_response.ok?, "Expected HTTP status code 200, got #{last_response.status} instead")There was a problem hiding this comment.
OK. It's also better than assert(last_response.ok?).
test/test_rack_server.rb
Outdated
| end | ||
|
|
||
| def test_multibyte_characters | ||
| assert_equal([true, "あいうえおかきくけこ"], call('test.add', "あいうえお", "かきくけこ")) |
There was a problem hiding this comment.
| assert_equal([true, "あいうえおかきくけこ"], call('test.add', "あいうえお", "かきくけこ")) | |
| assert_equal([true, "あいうえおかきくけこ"], call("test.add", "あいうえお", "かきくけこ")) |
| msg = <<-"MSGEND" | ||
| <html> | ||
| <head> | ||
| <title>#{err}</title> | ||
| </head> | ||
| <body> | ||
| <h1>#{err}</h1> | ||
| <p>Unexpected error occurred while processing XML-RPC request!</p> | ||
| </body> | ||
| </html> | ||
| MSGEND |
There was a problem hiding this comment.
| msg = <<-"MSGEND" | |
| <html> | |
| <head> | |
| <title>#{err}</title> | |
| </head> | |
| <body> | |
| <h1>#{err}</h1> | |
| <p>Unexpected error occurred while processing XML-RPC request!</p> | |
| </body> | |
| </html> | |
| MSGEND | |
| msg = <<-HTML | |
| <html> | |
| <head> | |
| <title>#{err}</title> | |
| </head> | |
| <body> | |
| <h1>#{err}</h1> | |
| <p>Unexpected error occurred while processing XML-RPC request!</p> | |
| </body> | |
| </html> | |
| HTML |
There was a problem hiding this comment.
We've got this exact same code snippet two more times in the existing code (CGIServer and ModRubyServer). I would prefer to keep this the same for now, and as a future work extract it to some shared code and remove this duplication. It's easier to find all the occurrences if we keep this exactly the same for now.
Once the code has been deduplicated, this improvement can be applied.
| return http_error(400, "Bad Request") unless parse_content_type(env['CONTENT_TYPE']).first == "text/xml" | ||
| return http_error(411, "Length Required") unless length > 0 | ||
|
|
||
| req = Rack::Request.new(env) |
There was a problem hiding this comment.
Do we need to require rack in initialize?
There was a problem hiding this comment.
I would guess this is already available when you run this as Rack middleware, so that should only be required if you run this rack app without rack. This seems like an unlikely scenario to me.
There was a problem hiding this comment.
OK. Let's revisit this when we receive a bug report / feature request about this.
There was a problem hiding this comment.
BTW, this is a Rack application not Rack middleware, right?
This is a simple Rack middleware that acts as an XMLRPC server. This can be used in any Rack compatible webserver.
|
Thanks. |
This is a simple Rack application that acts as an XMLRPC server. This can be used in any Rack compatible webserver.
There are a few gems that provide a Rack-based XMLRPC server (rack-rpc, xmlrpc-rack_server and threez-rack-rpc), but none of these have been updated in the past 10 years.
Implementation has mostly been copied from ModRubyServer, tests have been inspired by the WebrickServer tests